AWS Step FunctionsステートマシンからDynamoDBテーブルをQueryする
こんにちは、CX事業本部 IoT事業部の若槻です。
今回は、AWS Step FunctionsステートマシンからDynamoDBテーブルをQueryしてみました。
やってみた
対象のDynamoDBテーブル
下記のDynamoDBテーブルをクエリ対象とします。
- テーブル名:
crews
- PK:
crewId
(String) - GSI名:
areaId-index
- GSI-PK:
areaId
(String)
格納されているデータは以下となります。
ステートマシンの作成
Step Functions Workflow Studioでステートマシンを作成します。
Step Functionsのマネジメントコンソールでステートマシンの作成を開始します。
[次へ]をクリックします。
[action]をquery
で検索して[DynamoDB Query]をドラッグします。
[Query]の[設定]で、[APIパラメータ]で下記のJSONを指定します。ポイントはExpressionAttributeValues
の指定はDynamoDB Json形式とし、ExpressionAttributeNames
は通常のJson形式とすることです。(Step FunctionsでのDynamoDBテーブルのAPI操作ではDynamoDB.DocumentClient()
ではなくDynamoDB()
が使われるようですね。)指定したら[次へ]をクリックします。
{ "TableName": "crews", "IndexName": "areaId-index", "ExpressionAttributeNames": { "#areaId": "areaId" }, "ExpressionAttributeValues": { ":areaId": { "S.$": "$.areaId" } }, "KeyConditionExpression": "#areaId = :areaId" }
生成されたコードを確認したら[次へ]をクリックします。
生成されたコード(ステートマシン定義)は下記のようになります。
{ "Comment": "A description of my state machine", "StartAt": "Query", "States": { "Query": { "Type": "Task", "End": true, "Parameters": { "TableName": "crews", "IndexName": "areaId-index", "ExpressionAttributeNames": { "#areaId": "areaId" }, "ExpressionAttributeValues": { ":areaId": { "S.$": "$.areaId" } }, "KeyConditionExpression": "#areaId = :areaId" }, "Resource": "arn:aws:states:::aws-sdk:dynamodb:query" } } }
ステートマシンの作成を完了します。
ステートマシンを作成できました。不足しているDynamoDBへのアクセス権限を付与するために[IAMでロールを編集]をクリックします。
今回はAWS管理ポリシーのAmazonDynamoDBReadOnlyAccess
をアタッチしました。(ポリシーは必要に応じて用意してください)
動作
Step Functionsのコンソールに戻り、ステートマシンを実行します。入力はJSONを{"areaId": "<クエリしたいPK>"}
のように指定します。まずareaIdがa002
のアイテムを取得するクエリです。
{ "areaId": "a002" }
クエリが成功しました。areaIdがa002
のアイテムが取得できています。
次にareaIdがa001
のアイテムを取得するクエリです。
{ "areaId": "a001" }
クエリが成功しました。areaIdがa001
のアイテムが取得できています。
ハマった箇所
ExpressionAttributeValuesの指定方法の誤り
ステートマシンの定義でExpressionAttributeValues
の指定をDynamoDB Json形式としておらずエラーとなりハマりました。
{ "Comment": "A description of my state machine", "StartAt": "Query", "States": { "Query": { "Type": "Task", "End": true, "Parameters": { "TableName": "taxicrews", "IndexName": "areaId-index", "ExpressionAttributeNames": { "#areaId": "areaId" }, "ExpressionAttributeValues": { ":areaId.$": "$.areaId" }, "KeyConditionExpression": "#areaId = :areaId" }, "Resource": "arn:aws:states:::aws-sdk:dynamodb:query" } } }
上記定義に対して以下の入力をした場合、
{ "areaId": "a001" }
ステートマシンの実行が次のようなエラーとなります。
{ "error": "States.Runtime", "cause": "An error occurred while executing the state 'Query' (entered at the event id #2). The Parameters '{\"TableName\":\"taxicrews\",\"IndexName\":\"areaId-index\",\"ExpressionAttributeNames\":{\"#areaId\":\"areaId\"},\"ExpressionAttributeValues\":{\":areaId\":\"a001\"},\"KeyConditionExpression\":\"#areaId = :areaId\"}' could not be used to start the Task: [Cannot construct instance of `software.amazon.awssdk.services.dynamodb.model.AttributeValue$BuilderImpl` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('a001')]" }
ExpressionAttributeNamesの指定方法の誤り
ステートマシンの定義で逆にExpressionAttributeNames
の指定をDynamoDB Json形式としてしまった際もエラーとなりハマりました。
{ "Comment": "A description of my state machine", "StartAt": "Query", "States": { "Query": { "Type": "Task", "End": true, "Parameters": { "TableName": "taxicrews", "IndexName": "areaId-index", "ExpressionAttributeNames": { "#areaId": { "S": "areaId" } }, "ExpressionAttributeValues": { ":areaId": { "S.$": "$.areaId" } }, "KeyConditionExpression": "#areaId = :areaId" }, "Resource": "arn:aws:states:::aws-sdk:dynamodb:query" } } }
上記定義に対して以下の入力をした場合、
{ "areaId": "a001" }
Taskの実行が次のようなResourceNotFoundExceptionエラーとなります。
{ "resourceType": "aws-sdk:dynamodb", "resource": "query", "error": "DynamoDb.ResourceNotFoundException", "cause": "Requested resource not found (Service: DynamoDb, Status Code: 400, Request ID: c55042fb-70fa-426e-b03e-546c1b24de2f, Extended Request ID: null)" }
おわりに
AWS Step FunctionsステートマシンからDynamoDBテーブルをQueryしてみました。
DynamoDB()
のAPIを使用したクエリ操作というのをあまりやったことがなかったので結構ハマりましたが何とかできて良かったです。
参考
- Step Functions を使用した DynamoDB API の呼び出し - AWS Step Functions
- テーブルに対するクエリの実行 - Amazon DynamoDB
- Mission: Impossible – Ghost Protocol - Wikipedia
- AWS SDK for Node.js での DynamoDB と DynamoDB.DocumentClient の違い | DevelopersIO
以上